package im.oen.boot.common.utils;

import com.fasterxml.jackson.databind.JsonNode;

import java.lang.management.ManagementFactory;
import java.lang.management.MemoryMXBean;
import java.lang.management.MemoryUsage;
import java.lang.management.RuntimeMXBean;
import java.net.InetAddress;
import java.util.Properties;

/**
 * @author Kevin.Xu
 */
public class OSInfo {
    private static final RuntimeMXBean RUNTIME_MX_BEAN = ManagementFactory.getRuntimeMXBean();
    private static final MemoryMXBean MEMORY_MX_BEAN = ManagementFactory.getMemoryMXBean();
    private static final Properties SYS_PROPS = System.getProperties();
    private static final String OS = SYS_PROPS.getProperty("os.name").toLowerCase();

    public static String netIP() {
        String webIP = Runner.safeRun(() -> {
            WebClient.HttpResponse res = WebClient.get("https://ip.cn/api/index?type=0", null);
            if (!Checker.isSuccess(res)) {
                return null;
            }

            JsonNode obj = JsonUtil.safeToObj(res.getBodyString());
            if (obj == null) {
                return null;
            }
            JsonNode node = obj.get("ip");
            if (node == null) {
                return null;
            }
            String ip = node.asText();
            return (Checker.isNotEmpty(ip) && ip.length() > 7) ? ip : null;
        });
        return (Checker.isNotEmpty(webIP)) ? webIP : getHostIP();
    }

    public static boolean isLinux() {
        return OS.indexOf("linux") >= 0;
    }

    public static boolean isMacOS() {
        return OS.indexOf("mac") >= 0;
    }

    public static boolean isWindows() {
        return OS.indexOf("windows") >= 0;
    }

    public static int CPUs() {
        return Runtime.getRuntime().availableProcessors();
    }

    public static String localIP() {
        return "127.0.0.1";
    }

    public static String getOSName() {
        return SYS_PROPS.getProperty("os.name");
    }

    public static String getOSArch() {
        return SYS_PROPS.getProperty("os.arch");
    }

    public static String getUserDir() {
        return SYS_PROPS.getProperty("user.dir");
    }

    public static String getHostIP() {
        return Runner.safeRun(() -> {
            return InetAddress.getLocalHost().getHostAddress();
        }, "127.0.0.1");
    }

    public static String getHostName() {
        return Runner.safeRun(() -> {
            return InetAddress.getLocalHost().getHostName();
        }, "localhost");
    }

    public static double jdkTotalMemory() {
        return byteToMB(Runtime.getRuntime().totalMemory());
    }

    public static double jdkMaxMemory() {
        return byteToMB(Runtime.getRuntime().maxMemory());
    }

    public static double jdkFreeMemory() {
        return byteToMB(Runtime.getRuntime().freeMemory());
    }

    public static String jdkVersion() {
        return SYS_PROPS.getProperty("java.version");
    }

    public static String jdkHome() {
        return SYS_PROPS.getProperty("java.home");
    }

    public static String jdkName() {
        return RUNTIME_MX_BEAN.getSpecName();
    }

    public static long jvmStartTime() {
        return RUNTIME_MX_BEAN.getStartTime();
    }

    public static MemoryUsage jvmHeapMemoryUsage() {
        return MEMORY_MX_BEAN.getHeapMemoryUsage();
    }

    public static MemoryUsage jvmNonHeapMemoryUsage() {
        return MEMORY_MX_BEAN.getNonHeapMemoryUsage();
    }

    public static double byteToMB(long bytes) {
        double res = (double) bytes / 1024 / 1024;
        return (double) Math.round(res * 100) / 100;
    }
}
